
import { gameHelper } from '../../Utils/GameHelpler';
import { IKConstraint } from './IKConstraint';
const { ccclass, property, menu } = cc._decorator;
/**
 * 反向动力学关节
 */
@ccclass
@menu('cccframework/IKRoot')
export class IKRoot extends IKConstraint {

    @property(cc.Boolean)
    isFixed: boolean = false

    @property([cc.Node])
    _ikNodes: cc.Node[] = [];
    @property({ type: [cc.Node] })
    get ikNodes(): cc.Node[] {
        if (this._ikNodes[0] != this.node) {
            this._ikNodes.unshift(this.node)
        }
        return this._ikNodes;
    }
    set ikNodes(arr: cc.Node[]) {
        // arr = arr.filter((v) => {
        //     return v && v.getComponent(IKConstraint)
        // })
        arr.forEach(v => {
            gameHelper.addCompOnce(v, IKConstraint)
        })
        this._ikNodes = arr;
    }

    /**逆向计算上一个节点 */
    calcLast(curTarget: cc.Node, lastTarget: cc.Node) {
        // debugger
        let curWpos = curTarget.worldPosition;
        let lastWpos = lastTarget.worldPosition;
        let dist = lastTarget.getComponent(IKConstraint).distance
        let dir = lastWpos.sub(curWpos)

        // this.getLimitAngleDir(lastTarget, dir);

        dir.normalize().mul(dist)
        lastTarget.worldPosition = curWpos.add(dir)
        lastTarget.angle = -Math.atan2(dir.x, dir.y) / Math.PI * 180 + 180;
        // console.log('angle ', lastTarget.angle)
    }
    /**正向计算下一个节点 */
    calcNext(curTarget: cc.Node, nextTarget: cc.Node) {
        // debugger
        let curWpos = curTarget.worldPosition;
        let nextWpos = nextTarget.worldPosition;
        let dist = curTarget.getComponent(IKConstraint).distance
        let dir = nextWpos.sub(curWpos)

        this.getLimitAngleDir(curTarget, dir);

        dir.normalize().mul(dist)
        nextTarget.worldPosition = curWpos.add(dir)
        curTarget.angle = -Math.atan2(dir.x, dir.y) / Math.PI * 180;

    }
    /**限制关节角度 */
    getLimitAngleDir(curTarget: cc.Node, dir: cc.Vec2) {
        // let curIdx = this.ikNodes.indexOf(curTarget)
        // let lastTarget: cc.Node;
        // if (curIdx > 0 && curIdx < this.ikNodes.length - 1) {
        //     lastTarget = this.ikNodes[curIdx - 1]
        // }
        let angle = -Math.atan2(dir.x, dir.y) / Math.PI * 180;
        // if (lastTarget) {
        //     console.log('lastTarget', lastTarget.name)
        //     angle = gameHelper.vec2(dir).signAngle(
        //         gameHelper.vec2(lastTarget.worldPosition.sub(curTarget.worldPosition))
        //     )
        // }
        let angleLimit = curTarget.getComponent(IKConstraint).angleLimit;
        // let dstAngle = Math.abs(angle - angleLimit.x) < Math.abs(angle - angleLimit.y) ? angleLimit.x : angleLimit.y;
        // console.log('dstAngle', dstAngle)
        if (angle < angleLimit.x) {
            angle = angleLimit.x;
            // angle = dstAngle;
        }
        if (angle > angleLimit.y) {
            angle = angleLimit.y;
            // angle = dstAngle;
        }
        let rad = -angle * Math.PI / 180;
        dir.x = Math.sin(rad);
        dir.y = Math.cos(rad);
    }

    updatePos() {
        // gameHelper.clearDraw()
        if (this.ikNodes.length > 1) {
            for (let i = this.ikNodes.length - 1; i >= 0; i--) {
                if (i == 0) {
                    // gameHelper.drawAny({ radius: 30 }, this.ikNodes[i].worldPosition)
                    continue;
                }
                if (this.isFixed && i == 1) {
                    continue
                }
                this.calcLast(this.ikNodes[i], this.ikNodes[i - 1])
                // gameHelper.drawAny({ radius: 15 }, this.ikNodes[i].worldPosition)
            }
            // 反向约束
            if (this.isFixed) {
                for (let i = 0; i < this.ikNodes.length - 1; i++) {
                    this.calcNext(this.ikNodes[i], this.ikNodes[i + 1])
                    // gameHelper.drawAny({ radius: 15 }, this.ikNodes[i].worldPosition)
                }
            }
        }
    }

    lateUpdate() {
        this.updatePos()
    }
}
